﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[Serializable]
public class Triangle
{
    public Vector3[] mPoints;
    public Line[] mLines;
    public Vector3 planeNormal;

    [SerializeField]
    private int mIndex;
    public int Index
    {
        get { return mIndex; }
        set { mIndex = value;
            for (int i = 0; i < mLines.Length; i++)
            {
                mLines[i].mRightTriangle = mIndex;
            }
        }
    }

    public Triangle(Vector3 tPoint1, Vector3 tPoint2, Vector3 tPoint3)
    {
        mPoints = new Vector3[3] { tPoint1, tPoint2, tPoint3 };
        Line line1 = new Line(mPoints[0], mPoints[1]);
        Line line2 = new Line(mPoints[1], mPoints[2]);
        Line line3 = new Line(mPoints[2], mPoints[0]);
        mLines = new Line[3] { line1, line2, line3 };
        planeNormal = Vector3.Cross(mPoints[1] - mPoints[0], mPoints[2] - mPoints[0]);
    }

    public bool ContainPoint(Vector3 tPos)
    {
        bool inInter = PointInTriangle(new Vector2(mPoints[0].x, mPoints[0].z), new Vector2(mPoints[1].x, mPoints[1].z), new Vector2(mPoints[2].x, mPoints[2].z), new Vector2(tPos.x, tPos.z));
        float distance = DistanceToPlane(planeNormal, mPoints[0], tPos);
        Debug.LogFormat("{0} {1} {2}", planeNormal, mPoints[0], tPos, distance);
        return inInter && distance < 0.1f;
    }

    bool PointInTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
    {
        Vector2 v0 = C - A;
        Vector2 v1 = B - A;
        Vector2 v2 = P - A;

        float dot00 = Vector2.Dot(v0, v0);
        float dot01 = Vector2.Dot(v0, v1);
        float dot02 = Vector2.Dot(v0, v2);
        float dot11 = Vector2.Dot(v1, v1);
        float dot12 = Vector2.Dot(v1, v2);

        float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01);

        float u = (dot11 * dot02 - dot01 * dot12) * inverDeno;
        if (u < 0 || u > 1)
        {
            return false;
        }

        float v = (dot00 * dot12 - dot01 * dot02) * inverDeno;
        if (v < 0 || v > 1)
        {
            return false;
        }

        return u + v <= 1;
    }

    float DistanceToPlane(Vector3 planeNormal, Vector3 planePoint, Vector3 point)
    {
        // 单位化法向量
        planeNormal = planeNormal.normalized;

        // 计算角度
        float angle = Vector3.Angle(planeNormal, point - planePoint);

        // 计算距离
        return Mathf.Abs(planeNormal.magnitude * Mathf.Cos(angle * Mathf.Deg2Rad));
    }

    public Vector3 Center
    {
        get
        {
            return (mPoints[0] + mPoints[1] + mPoints[2]) / 3;
        }
    }
}
